#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>

void PrintInt(int x, int y)
{
    char s[32];
    char s2[32];
    itoa(x, s, 2);
    itoa(y, s2, 2);
    printf("\n\t变换前:%s\n\t变换后:%s\n", s, s2);
}

void Chapter_Two_Basic()
{
    int x = 0b01011000;
    int y = 0;

    printf("将最右侧的1位改为0.");
    y = x & (x - 1); // 将最右侧的1位改为0
    PrintInt(x, y);

    printf("检测是否为2^n - 1形式.");
    x = 0b01001100;
    y = (x & (x + 1)) == 1; //检测是否为2^n - 1形式
    PrintInt(x, y);

    x = 0b01011000;
    y = x & (-x); //析出最右侧1位
    printf("析出最右侧1位.");
    PrintInt(x, y);

    x += 0b11;
    y = ~x & (x + 1); //析出最右侧0位
    printf("析出最右侧0位.");
    PrintInt(x, y);
    x = x - x & 0b111;
    y = ~x & (x - 1); //识别后缀0的掩码,具有指令级的并行
    y = ~(x | -x);    //识别后缀0的掩码
    y = (x & -x) - 1; //识别后缀0的掩码
    y = x ^ (x - 1);  //识别最右侧的1位和后缀0的掩码
    y = x | x - 1;    //向右传播最右侧的1
    x = x | 0b111;
    y = ((x | (x - 1)) + 1) & x; //将最右侧的1位串改为0位串
    //对偶性
    y = x + 1 == x - 1 | ~(x + 1) == -x;
    //定理1：将字映射到字的函数可以使用字并行加、减、与、或、非指令实现
    //当且仅当函数结果每一位只依赖于每个输入操作数的对应位以及对应位的右侧的位。
    //即，尝试通过查看每个输入操作数的最右侧位来计算结果的最右侧位，
    //若不能如此计算则不能仅通过加减等指令实现
}

/*
寻找与一个给定的数具有相同数目1位的下一个大数
xxx0 1111 0000 ===>xxx1 0000 0111
*/
unsigned snoob(unsigned x)
{
    if (x == 0)
        return x;
    unsigned s, r, l;
    s = x & -x;
    r = x + s;
    l = x ^ r;
    l = (l >> 2) / s;
    return r | l;
}
/*
差或0函数
doz(x,y)= x-y ,if x>=y
        = 0 ,if x<y
*/
int doz(int x, int y)
{
    int d = x - y;
    return d & ((~(d ^ ((x ^ y) & (d ^ x)))) >> 31);
}
/*
不使用if条件语句的最大值函数
*/
int _max(int x, int y)
{
    return y + doz(x, y);
}

int _min(int x, int y)
{
    return x - doz(x, y);
}
int dozu(int x, int y)
{
    int d = x - y;
    return d & ~((~(d ^ ((~x ^ y) | ((x == y) & d)))) >> 31);
}
int _maxu(int x, int y)
{
    return y + dozu(x, y);
}

int _minu(int x, int y)
{
    return x - dozu(x, y);
}

//按位等值(与异或相反)，按位运算：位相等为1，不相等为0
int awdz(int x, int y)
{
    return ~(x ^ y);
}

int main()
{
    printf("Hack's Delight Experiment.\n\n");
    Chapter_Two_Basic();

    printf("\n\n%d,%d,%d\n", doz(11, 11), doz(11, 110), doz(110, 11));
    printf("\n\n%d,%d,%d\n", _max(11, 11), _max(11, 110), _max(110, 11));
    printf("\n\n%d,%d,%d\n", _min(11, 11), _min(11, 110), _min(110, 11));
    return 0;
}